package com.pdg.mcplugin.tsa;

import java.util.HashSet;
import java.util.logging.Logger;

import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.Event.Priority;
import org.bukkit.event.Event.Type;
import org.bukkit.permissions.Permission;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;

public class TSA extends JavaPlugin{

	//logger
	private Logger logger;
	public Logger getLogger(){
		if(logger==null){
			logger = Logger.getLogger(Constants.loggerName);
		}
		return logger;
	}
	
	//plugin manager
	private PluginManager pluginManager;
	public PluginManager getPluginManager(){
		if(pluginManager==null){
			pluginManager = getServer().getPluginManager();
		}
		return pluginManager;
	}
	
	//block listener
	private TSABlockListener blockListener;
	public TSABlockListener getBlockListener(){
		if(blockListener==null){
			blockListener = new TSABlockListener(this);
		}
		return blockListener;
	}
	
	//player listener
	private TSAPlayerListener playerListener;
	public TSAPlayerListener getPlayerListener(){
		if(playerListener==null){
			playerListener = new TSAPlayerListener(this);
		}
		return playerListener;
	}
	
	//server listener
	private TSAServerListener serverListener;
	public TSAServerListener getServerListener(){
		if(serverListener==null){
			serverListener = new TSAServerListener(this);
		}
		return serverListener;
	}
	
	//data provider
	private DataProvider dataProvider;
	public DataProvider getDataProvider(){
		if(dataProvider==null){
			dataProvider = new DataProvider(this);
		}
		return dataProvider;
	}
	
	//enable function
	public void onEnable(){
		getLogger().info(Constants.messageTSAEnabled);
		getPluginManager().registerEvent(Type.BLOCK_BREAK, getBlockListener(), Priority.Normal, this);
		getPluginManager().registerEvent(Type.SIGN_CHANGE, getBlockListener(), Priority.Normal, this);
		getPluginManager().registerEvent(Type.PLAYER_INTERACT,getPlayerListener(),Priority.Normal,this);
		getPluginManager().registerEvent(Type.PLUGIN_ENABLE,getServerListener(),Priority.Monitor,this);
		getPluginManager().registerEvent(Type.PLUGIN_DISABLE, getServerListener(), Priority.Monitor, this);
	}
	
	//disable function
	public void onDisable(){
		getLogger().info(Constants.messageTSADisabled);		
		blockListener = null;
		playerListener = null;
		serverListener = null;
		dataProvider = null;
	}
	
	private void showTSAGeneralHelp(CommandSender theCommandSender){
		for(String line: Constants.helpGeneral){
			theCommandSender.sendMessage(line);
		}
	}
	
	private void showArrivalSignHelp(CommandSender theCommandSender){
		for(String line: Constants.helpArrivalSign){
			theCommandSender.sendMessage(line);
		}
	}
	
	private void showDepartureSignHelp(CommandSender theCommandSender){
		for(String line: Constants.helpDepartureSign){
			theCommandSender.sendMessage(line);
		}
	}
	
	private void showContrabandHelp(CommandSender theCommandSender){
		for(String line: Constants.helpContraband){
			theCommandSender.sendMessage(line);
		}
	}
	
	private boolean hasContrabandCheck(Player player){
		//create permission if it doesn't exist
		if(getPluginManager().getPermission(Constants.permissionContrabandCheck)==null){
			getPluginManager().addPermission(new Permission(Constants.permissionContrabandCheck, Constants.permissionDefaultContrabandCheck));
		}
		return player.hasPermission(Constants.permissionContrabandCheck);
	}
	
	private boolean hasContrabandList(Player player){
		//create permission if it doesn't exist
		if(getPluginManager().getPermission(Constants.permissionContrabandList)==null){
			getPluginManager().addPermission(new Permission(Constants.permissionContrabandList, Constants.permissionDefaultContrabandList));
		}
		return player.hasPermission(Constants.permissionContrabandList);
	}
	
	private boolean hasContrabandPermit(Player player){
		//create permission if it doesn't exist
		if(getPluginManager().getPermission(Constants.permissionContrabandPermit)==null){
			getPluginManager().addPermission(new Permission(Constants.permissionContrabandPermit, Constants.permissionDefaultContrabandPermit));
		}
		return player.hasPermission(Constants.permissionContrabandPermit);
	}
	
	private boolean hasContrabandProhibit(Player player){
		//create permission if it doesn't exist
		if(getPluginManager().getPermission(Constants.permissionContrabandProhibit)==null){
			getPluginManager().addPermission(new Permission(Constants.permissionContrabandProhibit, Constants.permissionDefaultContrabandProhibit));
		}
		return player.hasPermission(Constants.permissionContrabandProhibit);
	}
	
	private boolean hasContrabandClear(Player player){
		//create permission if it doesn't exist
		if(getPluginManager().getPermission(Constants.permissionContrabandClear)==null){
			getPluginManager().addPermission(new Permission(Constants.permissionContrabandClear, Constants.permissionDefaultContrabandClear));
		}
		return player.hasPermission(Constants.permissionContrabandClear);
	}
	
	private void showContrabandList(CommandSender theCommandSender){
		if(theCommandSender instanceof Player){
			Player thePlayer = (Player)theCommandSender;
			if(!hasContrabandList(thePlayer)){
				thePlayer.sendMessage(Constants.errorNoPermissionToListContraband);
				return;
			}
		}
		HashSet<Material> materials = getDataProvider().listContraband();
		if(materials==null || materials.isEmpty()){
			theCommandSender.sendMessage(Constants.messageNoContrabandList);
		}else{
			String theList = "";
			for(Material material:materials){
				if(!theList.equalsIgnoreCase("")){
					theList+=",";
				}
				theList+=material.name().toLowerCase().replaceAll("_", " ");
			}
			theCommandSender.sendMessage(theList);
		}
	}
	
	private void permitContraband(CommandSender theCommandSender, Material theMaterial){
		if(theCommandSender instanceof Player){
			Player thePlayer = (Player)theCommandSender;
			if(!hasContrabandPermit(thePlayer)){
				thePlayer.sendMessage(Constants.errorNoPermissionToPermitContraband);
				return;
			}
		}
		if(getDataProvider().permitContraband(theMaterial)){
			theCommandSender.sendMessage(Constants.messagePermittedContraband);
		}else{
			theCommandSender.sendMessage(Constants.errorCouldNotPermitContraband);
		}
	}
	
	private void prohibitContraband(CommandSender theCommandSender, Material theMaterial){
		if(theCommandSender instanceof Player){
			Player thePlayer = (Player)theCommandSender;
			if(!hasContrabandProhibit(thePlayer)){
				thePlayer.sendMessage(Constants.errorNoPermissionToProhibitContraband);
				return;
			}
		}
		if(getDataProvider().prohibitContraband(theMaterial)){
			theCommandSender.sendMessage(Constants.messageProhibitedContraband);
		}else{
			theCommandSender.sendMessage(Constants.errorCouldNotProhibitContraband);
		}
		
	}
	
	private void checkContraband(CommandSender theCommandSender, Material theMaterial){
		if(theCommandSender instanceof Player){
			Player thePlayer = (Player)theCommandSender;
			if(!hasContrabandCheck(thePlayer)){
				thePlayer.sendMessage(Constants.errorNoPermissionToCheckContraband);
				return;
			}
		}
		if(getDataProvider().checkContraband(theMaterial)){
			theCommandSender.sendMessage(Constants.messageItemIsProhibited);
		}else{
			theCommandSender.sendMessage(Constants.messageItemIsPermitted);
		}
	}
	
	private void clearContraband(CommandSender theCommandSender){
		if(theCommandSender instanceof Player){
			Player thePlayer = (Player)theCommandSender;
			if(!hasContrabandClear(thePlayer)){
				thePlayer.sendMessage(Constants.errorNoPermissionToClearContraband);
				return;
			}
		}
		getDataProvider().clearContraband();
		theCommandSender.sendMessage(Constants.messageContrabandListCleared);
	}
		
	//command handler
	public boolean onCommand(CommandSender theCommandSender, Command theCommand, String theLabel, String[] theArgs){
		if(theLabel.equalsIgnoreCase(Constants.commandTSA)){
			if(theArgs.length==Constants.argCountZero || theArgs[Constants.argSubcommand].equalsIgnoreCase(Constants.subcommandHelp) || theArgs[Constants.argSubcommand].equalsIgnoreCase(Constants.subcommandQuestion)){
				showTSAGeneralHelp(theCommandSender);
				return true;
			} else if (theArgs[Constants.argSubcommand].equalsIgnoreCase(Constants.subcommandArrivalSign)){
				showArrivalSignHelp(theCommandSender);
				return true;
			} else if (theArgs[Constants.argSubcommand].equalsIgnoreCase(Constants.subcommandDepartureSign)){
				showDepartureSignHelp(theCommandSender);
				return true;
			} else if (theArgs[Constants.argSubcommand].equalsIgnoreCase(Constants.subcommandContraband)){
				if(theArgs.length==Constants.argCountSingle){
					showContrabandHelp(theCommandSender);
					return true;
				} else if(theArgs[Constants.argContrabandTask].equalsIgnoreCase(Constants.contrabandTaskList)){
					showContrabandList(theCommandSender);
					return true;
				}else if(theArgs[Constants.argContrabandTask].equalsIgnoreCase(Constants.contrabandTaskClear)){
					clearContraband(theCommandSender);
					return true;
				} else {
					if(theArgs.length<=Constants.argCountDouble){
						theCommandSender.sendMessage(Constants.errorNoItemName);
						return false;
					}
					String theItemName = "";
					for(Integer index = Constants.argItemNameStart;index<theArgs.length;++index){
						if(!theItemName.equalsIgnoreCase("")){
							theItemName += " ";
						}
						theItemName += theArgs[index];
					}
					Material theMaterial = Material.matchMaterial(theItemName);
					if(theMaterial==null){
						theCommandSender.sendMessage(String.format(Constants.errorInvalidItemName,theItemName));
						return false;
					}
					if(theArgs[Constants.argContrabandTask].equalsIgnoreCase(Constants.contrabandTaskPermit)){
						permitContraband(theCommandSender,theMaterial);
						return true;
					} else if(theArgs[Constants.argContrabandTask].equalsIgnoreCase(Constants.contrabandTaskProhibit)){
						prohibitContraband(theCommandSender,theMaterial);
						return true;
					} else if(theArgs[Constants.argContrabandTask].equalsIgnoreCase(Constants.contrabandTaskCheck)){
						checkContraband(theCommandSender,theMaterial);
						return true;
					}
				}
			}
		}
		return false;
	}
}
